﻿/**
 * Copyright (c) 2008 Justin Etheredge http://www.codethinked.com
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Microsoft Public License (Ms-PL)
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/ms-pl.html
 * If redistributing this code, this entire header must remain intact.
 * 
 * Some of the code in this application has been taken 
 * from the following sources (all of which are licensed under
 * the Ms-PL):
 * Matt Warren's Blog: http://blogs.msdn.com/mattwar/
 * MSDN: http://msdn2.microsoft.com/en-us/library/bb546158.aspx
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace LinqToSimpleDB
{
  internal class SimpleDBQueryContext
  {
    // Executes the expression tree that is passed to it.
    internal static object Execute(SimpleDBContext context, Expression expression, int precision, int scale)
    {
      // The expression must represent a query over the data source.
      if (!IsQueryOverDataSource(expression))
        throw new InvalidProgramException("No query over the data source was specified.");

      ItemFinder finder = new ItemFinder(expression);
      List<string> itemNames = finder.GetItemNames();

      IEnumerable<SimpleDBItem> items = null;
      if (itemNames.Count > 0)
      {
        items = context.GetItemsByName(itemNames);
      }
      else
      {
        string query = GetQueryText(context, expression, precision, scale);

        // Call the Web service and get the results.
        items = context.Query(query);
      }

      // Copy the IEnumerable places to an IQueryable.
      IQueryable<SimpleDBItem> queryableItems = items.AsQueryable<SimpleDBItem>();
      return queryableItems;
    }

    public static string GetQueryText(SimpleDBContext context, Expression expression, int precision, int scale)
    {
      // Get back the query that we send to SimpleDB
      QueryTranslator translator = new QueryTranslator(expression, precision, scale);
      return translator.Query;
    }

    private static bool IsQueryOverDataSource(Expression expression)
    {
      // If expression represents an unqueried IQueryable data source instance,
      // expression is of type ConstantExpression, not MethodCallExpression.
      return (expression is MethodCallExpression);
    }
  }
}
